<?php
/**
 * Created by PhpStorm.
 * User: bililovy
 * Date: 19-7-29
 * Time: 下午8:58
 * Description:
 */

namespace ServiceSdk\Utils\Encrypt;


class RSA
{
    /**
     * Description: 私钥加密 公钥解密
     *
     * @param string $data       明文数据
     * @param string $privatePem 加密的私钥
     *
     * @return mixed|string
     * @Author Bililovy
     * @Time   2021/9/26 15:35
     */
    public static function RSAPrivateEncrypt(string $data, string $privatePem)
    {
        //这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        $ssl = openssl_pkey_get_private($privatePem);
        $encryptedStr = "";
        foreach (str_split($data, 117) as $chunkStr) {
            openssl_private_encrypt($chunkStr, $encryptData, $ssl);
            $encryptedStr .= $encryptData;
        }

        //加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的
        return self::safeBase64Encode($encryptedStr);
    }


    /**
     * Description: 公钥解密
     *
     * @param string $encryptedData 秘文
     * @param string $publicPem     公钥
     *
     * @return string
     * @Author Bililovy
     * @Time   2021/9/26 15:37
     */
    public static function RSAPublicDecrypt(string $encryptedData, string $publicPem)
    {
        //这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        $ssl = openssl_pkey_get_public($publicPem);
        $decryptDataStr = '';
        foreach (str_split(self::safeBase64Decode($encryptedData), 128) as $chunkStr) {
            openssl_public_decrypt($chunkStr, $decryptData, $ssl);
            $decryptDataStr .= $decryptData;
        }

        return $decryptDataStr;
    }

    //加密码时把特殊符号替换成URL可以带的内容
    private static function safeBase64Encode(string $string)
    {
        $data = base64_encode($string);
        $data = str_replace(array ('+', '/', '='), array ('-', '_', ''), $data);

        return $data;
    }

    //解密码时把转换后的符号替换特殊符号
    private static function safeBase64Decode($string)
    {
        $data = str_replace(array ('-', '_'), array ('+', '/'), $string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }

        return base64_decode($data);
    }

    //生成公钥和私钥
    /**
     * 基于命令行 且安装了 openssl扩展
     * 1. 生成私钥：openssl genrsa -out rsa_private_key.pem 1024
     * 2. 通过私钥生成公钥：openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pe
     */
    /*public static function createSSLFile(string $sslFilePath, string $digist = 'randString')
    {

        $config = array (
            "digest_alg" => "xiaoyao",
            "private_key_bits" => 4096,           //字节数  512 1024 2048  4096 等 ,不能加引号，此处长度与加密的字符串长度有关系，可以自己测试一下
            "private_key_type" => OPENSSL_KEYTYPE_RSA,   //加密类型
        );
        $opensslConfigPath = "D:\PHPTutorial\Apache\conf\openssl.cnf"; //apache路径下的openssl.conf文件路径
        $res = openssl_pkey_new($config);
        if ( ! $res) {
            $config[ 'config' ] = $opensslConfigPath;
            $res = openssl_pkey_new($config);
        }
        //提取私钥
        openssl_pkey_export($res, $private_key, null, $config);

        //生成公钥
        $public_key = openssl_pkey_get_details($res);
        $public_key = $public_key[ "key" ];

        //公钥和私钥生成
        file_put_contents(ROOT_PATH . "ssl/cert_public.key", $public_key);
        file_put_contents(ROOT_PATH . "ssl/cert_private.pem", $private_key);





        $dn = array(
            "countryName" => 'zh', //所在国家名称
            "stateOrProvinceName" => 'GuangDong', //所在省份名称
            "localityName" => 'ShenZhen', //所在城市名称
            "organizationName" => 'baibai', //注册人姓名
            "organizationalUnitName" => 'company', //组织名称
            "commonName" => 'bbb', //公共名称
            "emailAddress" => '123@.qq.com' //邮箱
        );
        $privkeypass = 'cf'; //私钥密码
        $numberofdays = 3650; //有效时长
        $cerpath = "./test.cer"; //生成证书路径
        $pfxpath = "./test.pfx"; //密钥文件路径//生成证书
        $privkey = openssl_pkey_new();
        $csr = openssl_csr_new($dn, $privkey);
        $sscert = openssl_csr_sign($csr, null, $privkey, $numberofdays);
        openssl_x509_export_to_file($sscert, $cerpath); //导出证书到文件
        //openssl_pkcs12_export_to_file($sscert, $pfxpath, $privkey, $privkeypass); //生成密钥文件
        openssl_pkey_export_to_file($privkey, $pfxpath); //生成密钥文件
    }*/
}